﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using System.IO;
using System.Diagnostics;
using System.Security.Cryptography;

namespace WPFBASEncrypt
{
    /// <summary>
    /// Interaction logic for WindowEncrypt.xaml
    /// </summary>
    public partial class WindowEncrypt : Window
    {
        public WindowEncrypt()
        {
            InitializeComponent();
        }

        private void buttonSrc_Click(object sender, RoutedEventArgs e)
        {
            // MessageBox.Show("Browse Source Directory");
            System.Windows.Forms.FolderBrowserDialog dlg = new System.Windows.Forms.FolderBrowserDialog();
            dlg.ShowDialog();
            textBoxSrc.Text = dlg.SelectedPath;
        }

        private void buttonTt_Click(object sender, RoutedEventArgs e)
        {
            // MessageBox.Show("Browse Target Directory");
            System.Windows.Forms.FolderBrowserDialog dlg = new System.Windows.Forms.FolderBrowserDialog();
            dlg.ShowDialog();
            textBoxTt.Text = dlg.SelectedPath;
        }

        private void EncryptDir(DirectoryInfo sourceDir, DirectoryInfo targetDir)
        {
            foreach (FileInfo file in sourceDir.GetFiles())
            {
                // Encrypt each file with .BAS file extension
                if (!file.Extension.ToUpper().Equals(".BAS")) continue;

                EncryptFile(file.FullName, targetDir.FullName + @"\" + file.Name);
            }

            foreach (DirectoryInfo subSourceDir in sourceDir.GetDirectories())
            {
                // Go 
                DirectoryInfo subTargetDir = targetDir.CreateSubdirectory(subSourceDir.Name);
                EncryptDir(subSourceDir, subTargetDir);
            }
        }

        private void buttonEncrypt_Click(object sender, RoutedEventArgs e)
        {
            // MessageBox.Show("Start the encryption process");
            // EncryptFile(@"d:\sourceBAS\users.sys", @"d:\targetBAS\users.sys");
            if (!Directory.Exists(textBoxSrc.Text)) return;
            EncryptDir(new DirectoryInfo(textBoxSrc.Text), new DirectoryInfo(textBoxTt.Text));
        }

        private void DecryptDir(DirectoryInfo sourceDir, DirectoryInfo targetDir)
        {
            foreach (FileInfo file in sourceDir.GetFiles())
            {
                // Encrypt each file with .BAS file extension
                if (!file.Extension.ToUpper().Equals(".BAS")) continue;

                DecryptFile(file.FullName, targetDir.FullName + @"\" + file.Name);
            }

            foreach (DirectoryInfo subSourceDir in sourceDir.GetDirectories())
            {
                // Go 
                DirectoryInfo subTargetDir = targetDir.CreateSubdirectory(subSourceDir.Name);
                DecryptDir(subSourceDir, subTargetDir);
            }
        }

        private void buttonDecrypt_Click(object sender, RoutedEventArgs e)
        {
            // MessageBox.Show("Start the decryption process");
            // DecryptFile(@"d:\targetBAS\users.sys", @"d:\sourceBAS\users.sys");
            if (!Directory.Exists(textBoxSrc.Text)) return;
            DecryptDir(new DirectoryInfo(textBoxSrc.Text), new DirectoryInfo(textBoxTt.Text));
        }

        private void Cancel_Click(object sender, RoutedEventArgs e)
        {
            System.Environment.Exit(1);
        }

        public static String Simple1CompDecrypt(List<byte> dret)
        {
            // conver the content and then output to users.sys file
            StringBuilder builder = new StringBuilder();
            foreach (byte bt in dret)
            {
                if (bt == 0x0d)
                {
                    builder.Append("\r\n");                   

                }
                else if (bt == 0x0a)
                {
                    // Already process 0x0d
                    continue;
                }
                else
                {
                    // Convert the byte and append to the string
                    byte b = bt;
                    b = (byte)~b;
                    char c = (char)b;
                    builder.Append(c);
                }
            }
            return builder.ToString();
        }


        /// <summary>
        /// This API is used to encrypt a string
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static List<byte> Simple1CompEncrypt(String input)
        {
            // conver the content and then output to users.sys file
            List<byte> bList = new List<byte>();
            StringBuilder builder = new StringBuilder();
            // builder.Append("ABCD");
            builder.Append(input);

            for (int i = 0; i < builder.Length; i++)
            {
                if (builder[i] == '\r')
                {
                    bList.Add(0x0d);
                    bList.Add(0x0a);

                }
                else if (builder[i] == '\n')
                {
                    continue;
                }
                else
                {
                    byte ch = (byte)builder[i];
                    ch = (byte)~ch;
                    bList.Add(ch);
                }
            }
            return bList;
        }

        /// <summary>
        /// API for encypt a BAS file
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool EncryptFile(string source, string target)
        {
            StringBuilder builder = new StringBuilder();
            List<byte> dret = new List<byte>();
            FileStream rf = null;
            FileStream wf = null;
            BinaryWriter bw = null;
            StreamReader sr = null;
            try
            {
                // Read the file content
                rf = File.Open(source, FileMode.Open, FileAccess.Read);
                sr = new StreamReader(rf);
                try
                {
                    string line = "";
                    do
                    {
                        // Read the lines and append to the string builder
                        line = sr.ReadLine();
                        builder.AppendLine(line);
                    }
                    while (line != null);
                }
                catch (IOException)
                {
                    // Reach the end of the file.
                }

                // Encrypt the string
                dret = Simple1CompEncrypt(builder.ToString());

                // Write the string content
                wf = File.Open(target, FileMode.Create, FileAccess.Write);
                bw = new BinaryWriter(wf);
                foreach(byte b in dret) bw.Write(b);
            }
            catch(Exception e)
            {
                // output the debug message
                DefaultTraceListener dt = new DefaultTraceListener();
                Trace.Listeners.Add(dt);
                Debugger.Log(2, "Information", e.Message);
            }

            // close the handles
            if (bw != null) bw.Close();
            if (sr != null) sr.Close();
            if (wf != null) wf.Close();
            if (rf != null) rf.Close();
            return true;
        }

        /// <summarny>
        /// Decrypt a encrypted file
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool DecryptFile(string source, string target)
        {
            StringBuilder builder = new StringBuilder();
            List<byte> dret = new List<byte>();
            FileStream rf = null;
            FileStream wf = null;
            BinaryReader sr = null;
            StreamWriter sw = null;
            try
            {
                rf = File.Open(source, FileMode.Open, FileAccess.Read);
                sr = new BinaryReader(rf);
                do
                {
                    dret.Add(sr.ReadByte());
                } while (true);
            }
            catch (EndOfStreamException ex)
            {
                // read to the end of the file.
                builder.Append(Simple1CompDecrypt(dret));

                wf = File.Open(target, FileMode.Create, FileAccess.Write);
                sw = new StreamWriter(wf);
                sw.Write(builder.ToString());

                // output string of users.sys
                Debug.WriteLine(builder.ToString());
                Debug.WriteLine(ex.Message);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }

            // Close the file stream binary reader
            if (sr != null) sr.Close();
            if (rf != null) rf.Close();
            if (sw != null) sw.Close();
            if (wf != null) wf.Close();
            return true;
        }

        private void RemoveRecursive(DirectoryInfo dir)
        {
            try
            {
                // Make sure the directory exists
                if (!dir.Exists) return;


                // Get the files
                foreach (FileInfo file in dir.GetFiles())
                {
                    // Set the file attribute to not ready only.
                    file.Attributes &= ~FileAttributes.ReadOnly;                   
                    file.Delete();
                }

                // Get the directories
                foreach (DirectoryInfo subdir in dir.GetDirectories())
                {
                    RemoveRecursive(subdir);
                    subdir.Delete();
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }


        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            textBoxSrc.Text = @"d:\sourceBAS";
            textBoxTt.Text = @"d:\targetBAS";

            // RemoveRecursive(new DirectoryInfo(@"d:\deleteBAS"));

            //HashAlgorithm alg = new System.Security.Cryptography.SHA1CryptoServiceProvider();
            //
            //string password ="1234";
            //StringBuilder enpassword = new StringBuilder();
            //byte[] list = new byte[100];
            //byte[] enlist = new byte[100];
            //for (int i = 0; i < password.Length; i++) list[i] = (byte)password[i];
            //
            //enlist = alg.ComputeHash(list);
        }

    }
}
